package com.cctc.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.resource.VersionResourceResolver;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.List;

/**
 * @Name WebConfig
 * @Description: Web MVC 配置
 * @Author: lichao
 * @Email: li2chao@126.com
 * @Date: 2024-01-25 16:11:11
 **/
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // [类型转换器配置]
        // 1. 日期格式化配置
        DateFormatter dateFormatter = new DateFormatter("yyyy-MM-dd");
        registry.addFormatter(dateFormatter);
        // ... ...
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // [请求拦截器配置]
        // 1. 本地化拦截器配置
        registry.addInterceptor(new LocaleChangeInterceptor());
        // 2. 主题拦截器配置
        registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
        // ... ...
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // [CORS 配置]
        registry.addMapping("/api/**")
                .allowedOrigins("https://gulimall.com")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .maxAge(3600);
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // [请求内容协商类型配置]
        configurer.mediaType("json", MediaType.APPLICATION_JSON);
        configurer.mediaType("xml", MediaType.APPLICATION_XML);
        // ... ...
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // [消息转换器配置]
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
                .indentOutput(true)
                .dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
        // 1. 添加 Jackson JSON 和 XML 转换器
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
        // ... ...
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // [添加视图控制器]
        // 1. 默认 "/" 路径视图为 index.[jsp|html|...]
        registry.addViewController("/").setViewName("index");
        // ... ...
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        // [视图解析器配置]
        // 1. 使用 JSP 和 Jackson 作为 JSON 渲染的默认 View 来配置内容协商的视图解析
        registry.enableContentNegotiation(new MappingJackson2JsonView());
        registry.jsp();
        // ... ...
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // [静态资源处理器配置]
        /**
         * 1. /resources 路径的资源请求 -> /WebRoot/public、/static
         * 2. 这些资源在未来一年内到期，以确保最大限度地利用浏览器的缓存，减少浏览器的 HTTP 请求。
         * 3. 支持一个处理优化资源的工具链
         *    3.1 增加对所有静态资源的版本解析器。
         *    ... ...
         */
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public", "classpath:/static")
                .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)))
                .resourceChain(true)
                .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        // 默认 "/" Servlet 处理器配置
        configurer.enable("defaultRootPathServlet");
    }
}

